home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / progsrc / 3d_2 / 3d_2a.cpp < prev    next >
C/C++ Source or Header  |  1994-12-18  |  8KB  |  406 lines

  1. // 3D Rotation Program  3D_2.CPP
  2.  
  3. // adding edge class
  4.  
  5. // 18/12/94
  6. #define version "1.09"
  7.  
  8. //        sine angle lookup table added (floating point)
  9. //              transformation data read from data file
  10. //         calculates surface normals from shading
  11. //        support for OFF files via FILTER2 added
  12.  
  13.  
  14.  
  15. #include "3d_2a.h"
  16.  
  17.  
  18. // prototypes
  19.  
  20. void read_absolute_coords(char name[], surface *s_ptr, vector *v_ptr);
  21. void draw(surface *s_ptr, vector *e_ptr, int line_remove);
  22. void hidden_face_remove(matrix m_ptr, surface *s_ptr, vector *v_ptr);
  23. void image_clear(int x, int y);
  24. void convert_vertex_eye(matrix matr, vector *v_ptr, vector *e_ptr);
  25. void get_filename(char *file_name);
  26. void fast_kbflush(void);
  27. void grey_16_palette(void);
  28.  
  29.  
  30.  
  31. main(int argc, char *argv[])
  32. {
  33.  int hidden_line_removal = true;
  34.  int redraw = false;
  35.  matrix view;
  36.  clock_t start, stop;
  37.  
  38.  if (argc!=2)
  39.  {
  40.   cout << "\nRotates a 3D object.\n3D_2 [datafile._3d]\n";
  41.   exit(1);
  42.  }
  43.  
  44.  char file_name[80];
  45.  strcpy(file_name, argv[1]);
  46.  get_filename(&file_name[0]);    // get the file name
  47.  
  48.  ifstream in(file_name);
  49.  // if cann't open file then exit
  50.  if (!in)
  51.  {
  52.   cout << "Cannot open file " << file_name;
  53.   exit(1);
  54.  }
  55.  
  56.  in >> no_of_vertices;
  57.  in >> no_of_surfaces;
  58.  
  59.  vector *vertex, *eye_vertex;
  60.  surface *surf;
  61.  
  62.  vertex = new vector[no_of_vertices];
  63.  eye_vertex = new vector[no_of_vertices];
  64.  surf = new surface[no_of_surfaces];
  65.  
  66.  if (!surf || !vertex || !eye_vertex)
  67.  {
  68.   cout << "Allocation error\n";
  69.   exit(1);
  70.  }
  71.  
  72.  
  73.  read_absolute_coords(file_name, surf, vertex);
  74.  
  75.  
  76.  // goto graphics mode
  77.  int driver = VGA;
  78.  int mode = VGAHI;
  79.  initgraph(&driver, &mode, "");
  80.  int errorcode;
  81.  errorcode = graphresult();
  82.  if (errorcode != grOk)
  83.  {
  84.   cout << "Graphics error: " << grapherrormsg(errorcode) << "\n";
  85.   exit(1);
  86.  }
  87.  
  88.  setcolor(WHITE);
  89.  int x_max, y_max;
  90.  x_max = getmaxx();
  91.  y_max = getmaxy();
  92.  grey_16_palette();
  93.  
  94.  // calculate transformation matrix
  95.  view.calculate();
  96.  
  97.  // calculate normal vectors
  98.  for(int surfaceno=0; surfaceno<no_of_surfaces; surfaceno++)
  99.  {
  100.   surf[surfaceno].calculate_normal(vertex);
  101.  }
  102.  
  103.  hidden_face_remove(view, surf, vertex);
  104.  convert_vertex_eye(view, vertex, eye_vertex);
  105.  draw(surf, eye_vertex, hidden_line_removal);
  106.  
  107.  
  108.  int ch;
  109.  do
  110.  {
  111.   ch = getch();
  112.   if (ch==0) ch = getch() + 256;
  113.   fast_kbflush();
  114.   redraw = false;
  115.  
  116.   switch (ch)
  117.   {
  118.    case 328:
  119.    view.set_phi(5);
  120.    redraw = true;
  121.    break;
  122.    case 336: //
  123.    view.set_phi(-5);
  124.    redraw = true;
  125.    break;
  126.    case 333: // 'right' arrow key
  127.    view.set_theta(5);
  128.    redraw = true;
  129.    break;
  130.    case 331: // 'left' arrow key
  131.    view.set_theta(-5);
  132.    redraw = true;
  133.    break;
  134.    case 45:  // '+' key
  135.    view.set_rho(20);
  136.    redraw = true;
  137.    break;
  138.    case 43:  // '-' key
  139.    view.set_rho(-20);
  140.    redraw = true;
  141.    break;
  142.    case 104: // 'h' key
  143.    // if hidden line removal on then turn off, and vice-versa
  144.    hidden_line_removal = hidden_line_removal ? false : true;
  145.    redraw = true;
  146.    break;
  147.    default:
  148.    break;
  149.   }
  150.   if (redraw)
  151.   {
  152.    // remove old image
  153.    image_clear(x_max, y_max);
  154.  
  155.    // draw new image
  156.    start = clock();
  157.    view.calculate();
  158.    if (hidden_line_removal) hidden_face_remove(view, surf, vertex);
  159.    convert_vertex_eye(view, vertex, eye_vertex);
  160.    draw(surf, eye_vertex, hidden_line_removal);
  161.    stop = clock();
  162.   }
  163.  } while (ch != 113);  // 'q' key
  164.  
  165.  
  166.  // return back to dos
  167.  restorecrtmode();
  168.  cout << "\n3D Rotation program version " << version << "\n";
  169.  cout << "Compiled on " << __DATE__ << " at " << __TIME__  << "\n";
  170.  printf("The time was: %f\n", (stop - start) / CLK_TCK);
  171.  exit(0);
  172. }
  173.  
  174.  
  175. void draw(surface *s_ptr, vector *e_ptr, int line_remove)
  176. {
  177.  float xe,ye,ze;
  178.  int xs,ys;
  179.  int q, p, *poly, num;
  180.  
  181.  int screendist = 2000;
  182.  int surfaceno;
  183.  
  184.  for(surfaceno=0; surfaceno<no_of_surfaces; surfaceno++)
  185.  {
  186.   // if visible draw surface or if hidden line removal off
  187.   if ((s_ptr[surfaceno].get_visible()) || (!line_remove))
  188.   {
  189.    num = s_ptr[surfaceno].get_no_of_verts();
  190.    p = (num*2)+2;
  191.    poly = new int[p];
  192.    if (!poly) exit(1);
  193.  
  194.    int j;
  195.  
  196.    for(j=0; j<s_ptr[surfaceno].get_no_of_verts(); j++)
  197.    {
  198.     q = s_ptr[surfaceno].get_vert(j);
  199.  
  200.     xe = e_ptr[q].get_x();
  201.     ye = e_ptr[q].get_y();
  202.     ze = e_ptr[q].get_z();
  203.  
  204.     xs = screendist * (xe / ze);
  205.     ys = screendist * (ye / ze);
  206.  
  207.     if (!j)
  208.      {
  209.       poly[(num*2)] = xs + origin_x;
  210.       poly[(num*2)+1] = ys + origin_y;
  211.       //moveto (xs + origin_x, ys + origin_y);
  212.      }
  213.  
  214.     poly[j*2] = xs + origin_x;
  215.     poly[(j*2)+1] = ys + origin_y;
  216.    }
  217.  
  218.    if (!line_remove)   drawpoly((p/2), poly);
  219.     else
  220.     {
  221.      setfillstyle(SOLID_FILL, s_ptr[surfaceno].get_shading());
  222.      fillpoly((p/2),poly);
  223.     }
  224.  
  225.    delete [p] poly;
  226.   }
  227.  }
  228. }
  229.  
  230.  
  231.  
  232.  
  233. // initialise the arrays
  234. void read_absolute_coords(char name[], surface *s_ptr, vector *v_ptr)
  235. {
  236.  int no,x,y,z;
  237.  char ch;
  238.  
  239.  ifstream in(name);
  240.  // if cann't open file then exit
  241.  if (!in)
  242.  {
  243.   exit(1);
  244.  }
  245.  
  246.  cout << "Reading data file " << name << "\n";
  247.  
  248.  
  249.  int tmp_num;
  250.  in >> tmp_num;                // find no. of vertices
  251.  in >> tmp_num;            // find no. of surfaces
  252.  in >> tmp_num;            // total no. of vertices & surfaces
  253.  
  254.  
  255.  for(int i=0; i<no_of_vertices; i++)
  256.  {
  257.   in >> x;
  258.   in >> y;
  259.   in >> z;
  260.   v_ptr[i].assign(x,y,z);
  261.  }
  262.  
  263.  int vertice;
  264.  int vert[9];
  265.  for(i=0; i<no_of_surfaces; i++)
  266.  {
  267.   in >> vertice;
  268.   if (vertice > 8)
  269.   {
  270.    cout << "\nAt present can only a max. of 8 vertices to a surface\n";
  271.    exit(1);
  272.   }
  273.   s_ptr[i].init_vert(vertice);
  274.   for(int j=0; j<vertice; j++)
  275.   {
  276.    in >> vert[j];
  277.    if (vert[j] < 0)
  278.    {
  279.     cout << "\nVertex number is -ve\n";
  280.     exit(1);
  281.    }
  282.   }
  283.   s_ptr[i].set_vert(vert);
  284.  }
  285.  
  286.  in.close();
  287. }
  288.  
  289.  
  290.  
  291. void hidden_face_remove(matrix m_ptr, surface *s_ptr, vector *v_ptr)
  292. {
  293.  vector view;
  294.  {
  295.   float sin_phi;
  296.   int theta, phi, rho;
  297.  
  298.   theta = m_ptr.get_theta();
  299.   phi = m_ptr.get_phi();
  300.   rho = m_ptr.get_rho();
  301.  
  302.   sin_phi = f_sin(phi);
  303.  
  304.   long v1,v2,v3;
  305.   v1 = rho * sin_phi * f_cos(theta);
  306.   v2 = rho * sin_phi * f_sin(theta);
  307.   v3 = rho * f_cos(phi);
  308.   view.assign(v1,v2,v3);
  309.  }
  310.  
  311.  int surfaceno, t0;
  312.  vector los;
  313.  
  314.  for (surfaceno=0; surfaceno<no_of_surfaces; surfaceno++)
  315.  {
  316.   // calculate line of sight vectors
  317.   t0 = s_ptr[surfaceno].get_vert(0);
  318.   los = view - v_ptr[t0];
  319.  
  320.   // is it visible ?
  321.   //s_ptr[surfaceno].calculate_visibility(los);
  322.   s_ptr[surfaceno].calculate_shading(los);
  323.  }
  324. }
  325.  
  326. // clears the image
  327. void image_clear(int x, int y)
  328. {
  329.  int box[] = {0,0, 0,y+1, x,y+1, x,0};
  330.  int color;
  331.  color = getcolor();
  332.  setcolor(BLACK);
  333.  setfillstyle(SOLID_FILL, BLACK);
  334.  fillpoly(4,box);
  335.  setcolor(color);
  336. }
  337.  
  338.  
  339. // converts the world co-ordinates into eye co-ordinates
  340. void convert_vertex_eye(matrix matr, vector *v_ptr, vector *e_ptr)
  341. {
  342.  vector temp;
  343.  
  344.  for(int vertexno=0; vertexno<no_of_vertices; vertexno++)
  345.  {
  346.   temp.assign(v_ptr[vertexno]);
  347.  
  348.   // multiply vector with matrix
  349.   temp = temp * (matr);
  350.  
  351.   e_ptr[vertexno].assign(temp);
  352.  }
  353. }
  354.  
  355. // set the 16 colour palette to 15 shades of grey
  356. void grey_16_palette(void)
  357. {
  358.  register int j;
  359.  struct palettetype pal;
  360.  
  361.  // load the colour palette with the 15 shades of grey
  362.  getpalette (&pal);
  363.  
  364.  for (j=0; j<pal.size; j++)
  365.    setrgbpalette (pal.colors[j], j*4, j*4, j*4);
  366. }
  367.  
  368.  
  369. void fast_kbflush(void)
  370. {
  371.  *((unsigned far *)MK_FP(0x40, 0x1a)) = *((unsigned far *)MK_FP(0x40, 0x1c));
  372. }
  373.  
  374.  
  375. // append a ._3d to the file name
  376. void get_filename(char *file_name)
  377. {
  378.   char drive[3];
  379.   char dir[66];
  380.   char fname[9];
  381.   char file[9];
  382.   char ext[5];
  383.   int flag;
  384.  
  385.   flag = fnsplit(file_name, drive, dir, fname, ext);
  386.   if (flag & WILDCARDS)
  387.   {
  388.    cout << "Wildcard found in file name.\n";
  389.    exit(1);
  390.   }
  391.  
  392.   if (!(flag & FILENAME))
  393.   {
  394.    cout << "A file name is required!\n";
  395.    exit(1);
  396.   }
  397.  
  398.   getcwd(file_name,MAXPATH);      // get current directory
  399.   strcat(file_name,"\\");        // append a trailing \
  400.   fnsplit(file_name,drive,dir,file,ext);
  401.   strupr(fname);
  402.   strcpy(file,fname);
  403.   strcpy(ext,"._3D");
  404.   // read file from the current dir
  405.   fnmerge(file_name,drive,dir,file,ext);
  406. }